package org.ddd.book.domain.book.entity;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.ddd.book.domain.IBaseEntity;
import org.ddd.book.domain.base.vo.AddressVO;
import org.ddd.book.domain.book.event.LibraryRemoveEvent;
import org.ddd.book.domain.book.repository.IBookroomRepository;
import org.ddd.book.domain.book.repository.ILibraryRepository;
import org.ddd.book.domain.book.vo.LibraryBaseInfoVO;
import org.ddd.book.domain.factoty.EventFactory;
import org.ddd.book.domain.factoty.RepositoryFactory;
import org.ddd.book.domain.security.vo.UserVO;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 图书馆实体（真实世界中，一座城市会有多个图书馆，甚至一所学校也会存在多个图书馆）
 */
@Getter
@Setter
@Slf4j
public class LibraryEntity implements IBaseEntity {
    // 唯一标识
    private Long id;
    // 图书馆名称
    private String libraryName;
    // 图书馆所在地址
    private AddressVO address;
    // 馆长
    private UserVO admin;
    // 基本信息
    private LibraryBaseInfoVO baseInfo;

    public AddressVO getAddress() {
        if (null == address) {
            address = RepositoryFactory.get(ILibraryRepository.class).findAddress(id);
        }
        return address;
    }

    public UserVO getAdmin() {
        if (null == admin) {
            // TODO 加载admin
            return null;
        }
        return admin;
    }

    /**
     * 所有图书室
     *
     * @return List<BookroomEntity>
     */
    public List<BookroomEntity> allBookroom() {
        return RepositoryFactory.get(IBookroomRepository.class).libraryBookroomList(id);
    }

    /**
     * 查找图书室
     *
     * @param bookroomName 图书室名称
     * @return BookroomEntity
     */
    public BookroomEntity findBookroom(String bookroomName) {
        return RepositoryFactory.get(IBookroomRepository.class).findByLibraryAndBookroomName(id, bookroomName);
    }

    /**
     * 增加图书室
     *
     * @param bookroom 图书室
     */
    public void addBookRoom(BookroomEntity bookroom) {
        bookroom.setLibrary(id);
        // 持久化
        bookroom.save();
    }

    /**
     * 移除图书室
     *
     * @param bookroomName 图书室名称
     */
    public void removeBookRoom(String bookroomName) {
        BookroomEntity bookroom = findBookroom(bookroomName);
        if (null == bookroom) {
            throw new IllegalArgumentException("bookroom not exist!");
        }
        bookroom.remove();
    }

    private void checkParams() {
        if (!StringUtils.hasText(libraryName)) {
            throw new IllegalArgumentException("library name can not be empty!");
        }
        if (null == id) {
            // 新建的时候，需要检查这些参数
            if (null == address) {
                throw new IllegalArgumentException("address can not be null!");
            }
            if (null == admin) {
                throw new IllegalArgumentException("admin can not be null!");
            }
        }
    }

    @Override
    public void save() {
        // 检查参数是否合规
        checkParams();
        ILibraryRepository iLibraryRepository = RepositoryFactory.get(ILibraryRepository.class);
        // 判断是否有重名的
        LibraryEntity existLibrary = iLibraryRepository.findByLibraryName(libraryName);
        if (existLibrary != null && !existLibrary.getId().equals(id)) {
            throw new IllegalArgumentException("library name [" + libraryName + "] already exist!");
        }
        // ID由资源库自行生成
        iLibraryRepository.save(this);
    }

    @Override
    public void remove() {
        if (null == id) {
            throw new IllegalArgumentException("id is empty!");
        }
        // 从存储层删除
        RepositoryFactory.get(ILibraryRepository.class).remove(id);
        // 产生领域事件
        LibraryRemoveEvent event = new LibraryRemoveEvent();
        event.setLibraryId(id);
        EventFactory.publishEvent(event);
    }

    public void updateBaseInfoMessage(LibraryBaseInfoVO newBaseInfo) {
        this.baseInfo = newBaseInfo;
        save();
    }
}
